package com.elicitor.svm;

import libsvm.*;
import java.io.*;
import java.util.*;

public class SVMPredict {

    
    private static Double out;
    
    private static double atof(String s) {
        return Double.valueOf(s).doubleValue();
    }

    private static int atoi(String s) {
        return Integer.parseInt(s);
    }

    private static void predict(BufferedReader input, DataOutputStream output, svm_model model, int predict_probability) throws IOException {
        int correct = 0;
        int total = 0;
        double error = 0;
        double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;

        int svm_type = svm.svm_get_svm_type(model);
        int nr_class = svm.svm_get_nr_class(model);
        double[] prob_estimates = null;

        if (predict_probability == 1) {
            if (svm_type == svm_parameter.EPSILON_SVR
                    || svm_type == svm_parameter.NU_SVR) {
                System.out.print("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=" + svm.svm_get_svr_probability(model) + "\n");
            } else {
                int[] labels = new int[nr_class];
                svm.svm_get_labels(model, labels);
                prob_estimates = new double[nr_class];
                output.writeBytes("labels");
                for (int j = 0; j < nr_class; j++) {
                    output.writeBytes(" " + labels[j]);
                }
                output.writeBytes("\n");
            }
        }
        while (true) {
            String line = input.readLine();
            if (line == null) {
                break;
            }

            StringTokenizer st = new StringTokenizer(line, " \t\n\r\f:,");

            double target = atof("1");
            int m = st.countTokens();
            svm_node[] x = new svm_node[m];
            for (int j = 0; j < m; j++) {
                //if(m==24)System.out.print(j+ " : ss :"+target+"\n");
                x[j] = new svm_node();
                x[j].index = j;
                x[j].value = atof(st.nextToken());
            }

            double v;
            if (predict_probability == 1 && (svm_type == svm_parameter.C_SVC || svm_type == svm_parameter.NU_SVC)) {
                v = svm.svm_predict_probability(model, x, prob_estimates);
                output.writeBytes(v + " ");
                for (int j = 0; j < nr_class; j++) {
                    output.writeBytes(prob_estimates[j] + " ");
                }
                output.writeBytes("\n");
            } else {
                v = svm.svm_predict(model, x);
                System.out.println(target + " : " + v);
                output.writeBytes(v + "\n");
                out = v;
            }

            if (v == target) {
                ++correct;
            }
            error += (v - target) * (v - target);
            sumv += v;
            sumy += target;
            sumvv += v * v;
            sumyy += target * target;
            sumvy += v * target;
            ++total;
        }
        if (svm_type == svm_parameter.EPSILON_SVR
                || svm_type == svm_parameter.NU_SVR) {
            System.out.print("Mean squared error = " + error / total + " (regression)\n");
            System.out.print("Squared correlation coefficient = "
                    + ((total * sumvy - sumv * sumy) * (total * sumvy - sumv * sumy))
                    / ((total * sumvv - sumv * sumv) * (total * sumyy - sumy * sumy))
                    + " (regression)\n");
        } else {
            System.out.print("Accuracy = " + (double) correct / total * 100
                    + "% (" + correct + "/" + total + ") (classification)\n");
        }
    }

    private static void exit_with_help() {
        System.err.print("usage: svm_predict [options] test_file model_file output_file\n"
                + "options:\n"
                + "-b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0); one-class SVM not supported yet\n");
        System.exit(1);
    }

    public static double Analyze(String inputData, String modelFileName, String outputFileName) throws FileNotFoundException, IOException {
        int i, predict_probability = 0;
        out = 7.0;
        try {
            BufferedReader input = new BufferedReader(new FileReader(inputData));
            DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outputFileName)));
            svm_model model = svm.svm_load_model(modelFileName);
            if (predict_probability == 1) {
                if (svm.svm_check_probability_model(model) == 0) {
                    System.err.print("Model does not support probabiliy estimates\n");
                    System.exit(1);
                }
            } else {
                if (svm.svm_check_probability_model(model) != 0) {
                    System.out.print("Model supports probability estimates, but disabled in prediction.\n");
                }
            }
            predict(input, output, model, predict_probability);
            input.close();
            output.close();
        } catch (ArrayIndexOutOfBoundsException e) {
            exit_with_help();
        }
        return out;
    }
}
